﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
using ICRprojekt.Properties;
using ICRprojekt.UcitavanjePitanja;
using ICRprojekt.Vibracija;
using Timer=System.Windows.Forms.Timer;

namespace ICRprojekt
{
    public partial class GlavnaForma : Form
    {
        private const int SEKUNDA = 1000;
        private const int MILISEC_VibrateClick = 30;

        private bool iskoristen_JDS;
        private Igra _igra;
        private int tocnih_zaredom;
        private int zatvorenih_slika_pitanje_ukupno;
        private Dictionary<KategorijaPitanja, int> zatvorenih_po_kategoriji;
        private List<SlikaPitanje> lista_okvira;
        private SlikaPitanje AktivnaSlika;

        public GlavnaForma( )
        {
            InitializeComponent( );
        }

        /// <summary>
        /// Generira novu igru na glavnoj formi
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void NovaIgra_Click( object sender, EventArgs e )
        {
            panel_glavni_izbornik.Visible = false;
            LED.Vibrate( MILISEC_VibrateClick );
            // stvori novu igru i inicijaliziraj glavni Timer
            _igra = new Igra( );
            _igra.glavni_timer = new Timer( );
            _igra.glavni_timer.Tick += glavni_timer_Tick;
            _igra.glavni_timer.Interval = SEKUNDA;

            // inicijaliziraj tocne zaredom
            tocnih_zaredom = 0;

            // inicijaliziraj i kratki Timer
            _igra.timer_pitanja = new Timer( );
            _igra.timer_pitanja.Tick += timer_pitanja_Tick;
            _igra.timer_pitanja.Interval = SEKUNDA;

            List<Pitanje> pitanja = _igra.GenerirajIgru( );
            int brojac_pitanja = 0;

            // spremi sve okvire u listu da se moze iterirati kroz njih
            lista_okvira = new List<SlikaPitanje>
                               {
                                   slikaPitanje_11,slikaPitanje_12,slikaPitanje_13,slikaPitanje_14,
                                   slikaPitanje_21,slikaPitanje_22,slikaPitanje_23,slikaPitanje_24,
                                   slikaPitanje_31,slikaPitanje_32,slikaPitanje_33,slikaPitanje_34,
                                   slikaPitanje_41,slikaPitanje_42,slikaPitanje_43,slikaPitanje_44
                               };

            // spremi Pitanja u Slike
            foreach ( var slika_pitanje in lista_okvira )
            {
                var pitanje = pitanja[brojac_pitanja];
                slika_pitanje.Pitanje = pitanje;
                slika_pitanje.Image = OdrediSliku( pitanje.Kategorija );
                slika_pitanje.Enabled = true;
                brojac_pitanja++;
            }

            ShowPanel_glavni( );
            // prikazi traku za tocno netocno i vrijeme, rezultat
            lab_tocno_netocno.Visible = true; 
            lab_preostalo_sekundi.Visible = true;

            // pokreni glavni brojac
            _igra.glavni_timer.Enabled = true;

            // omoguci zaustavljanje igre
            predajIgru.Enabled = true;

            // resetiraj igru
            _igra.Rezultat = 0;
            _igra.Ukupni_broj_sekundi = 600;
            zatvorenih_slika_pitanje_ukupno = 0;
            InicijalizirajPopisZatvorenih( );
        }

        /// <summary>
        /// Metoda inicijalizira brojac zatvorenih pitanja po kategoriji.
        /// </summary>
        private void InicijalizirajPopisZatvorenih()
        {
            zatvorenih_po_kategoriji = new Dictionary<KategorijaPitanja, int>
                                           {
                                               {KategorijaPitanja.Zemljopis,0},
                                               {KategorijaPitanja.Sport,0},
                                               {KategorijaPitanja.Povijest,0},
                                               {KategorijaPitanja.Kultura,0},
                                               {KategorijaPitanja.JDS,0}
                                           };
        }

        /// <summary>
        /// Obrada kratkog timera.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void timer_pitanja_Tick( object sender, EventArgs e )
        {
            _igra.Brojac_kratki--;
            if ( _igra.Brojac_kratki != 0 )
                lab_preostalo_sekundi.Text = _igra.Brojac_kratki.ToString( );
            else
            {
                tocnih_zaredom = 0;
                Zvuk.Zvuk_Netocno();
                lab_preostalo_sekundi.Text = "0";
                lab_tocno_netocno.Text = "Vrijeme!";
                lab_tocno_netocno.BackColor = Color.Red;
                // makni tipkovnicu
                inputPanel1.Enabled = false;
                // zaustavi timer
                _igra.timer_pitanja.Enabled = false;
                Refresh( );
                // nakon sekunde vrati se na glavni meni
                Pricekaj( 2 );
                ResetirajTocno( );

                ShowPanel_glavni( );
            }
        }

        /// <summary>
        /// Funkcija koja se izvodi svaki put kada Timer otkuca (svake sekunde)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void glavni_timer_Tick( object sender, EventArgs e )
        {
            _igra.Ukupni_broj_sekundi--;

            // provjeravamo kraj igre ako su odgovorena sva pitanja
            if (zatvorenih_slika_pitanje_ukupno == 20)
            {
                Zvuk.Zvuk_UspjesanKraj();
                _igra.Ukupni_broj_sekundi = 0;
            }

            // ako nije kraj
            if (_igra.Ukupni_broj_sekundi != 0)
                progressBar1.Value = _igra.Ukupni_broj_sekundi;
            else
            {
                progressBar1.Value = 0;
                lab_tocno_netocno.Text = "Kraj Igre!";
                // zatvori sva pitanja
                for( int i=0; i<lista_okvira.Count; i++ )
                {
                    // zakljucaj to pitanje
                    lista_okvira[i].Enabled = false;
                    lista_okvira[i].Image = OdrediSlikuRjeseno(lista_okvira[i].Pitanje.Kategorija);
                }
                // zaustaviti glavni tajmer
                _igra.glavni_timer.Enabled = false;
                Obradi_Rezultat();
            }
        }

        /// <summary>
        /// Metoda dodaje novi highscore.
        /// </summary>
        private void Obradi_Rezultat()
        {
            var ih = new IspisHighscore((int)_igra.Rezultat) {Enabled = true};
            ih.Show();
        }

        /// <summary>
        /// Vraca sliku kategorije za zadano ime kategorije
        /// </summary>
        /// <param name="kategorijaPitanja">kategorija</param>
        /// <returns>slika kategorije</returns>
        private Image OdrediSliku( KategorijaPitanja kategorijaPitanja )
        {
            if ( kategorijaPitanja == KategorijaPitanja.Zemljopis )
                return Resources._icr_menu_item_zemljopis;
            if ( kategorijaPitanja == KategorijaPitanja.Povijest )
                return Resources._icr_menu_item_povijest;
            if ( kategorijaPitanja == KategorijaPitanja.Sport )
                return Resources._icr_menu_item_sport;
            if ( kategorijaPitanja == KategorijaPitanja.Kultura )
                return Resources._icr_menu_item_kultura;
            if (kategorijaPitanja == KategorijaPitanja.JDS)
                return Resources._icr_menu_item_JDS;
            return null;
        }

        /// <summary>
        /// Vraca sliku kategorije za zadano ime kategorije
        /// </summary>
        /// <param name="kategorijaPitanja">kategorija</param>
        /// <returns>slika kategorije</returns>
        private Image OdrediSlikuRjeseno( KategorijaPitanja kategorijaPitanja )
        {
            if ( kategorijaPitanja == KategorijaPitanja.Zemljopis )
                return Resources._icr_menu_item_zemljopis_solved;
            if ( kategorijaPitanja == KategorijaPitanja.Povijest )
                return Resources._icr_menu_item_povijest_solved;
            if ( kategorijaPitanja == KategorijaPitanja.Sport )
                return Resources._icr_menu_item_sport_solved;
            if ( kategorijaPitanja == KategorijaPitanja.Kultura )
                return Resources._icr_menu_item_kultura_solved;
            if ( kategorijaPitanja == KategorijaPitanja.JDS )
                return Resources._icr_menu_item_JDS_solved;
            return null;
        }

        /// <summary>
        /// Funkcija koja obraduje klik na sliku pitanja. Otvara prvo pitanje i pokrece tajmer za odgovor.
        /// </summary>
        /// <param name="sender"></param>
        private void ObradiKlikPitanja( object sender )
        {
            LED.Vibrate( MILISEC_VibrateClick );
            Zvuk.Zvuk_OtvoriPitanje();
            AktivnaSlika = ( (SlikaPitanje) sender );
            _igra.Aktivno_pitanje = AktivnaSlika.Pitanje;
            // uvecaj broj otvaranja
            AktivnaSlika.Pitanje.BrojOtvaranja++;
            // postavi pitanja i odgovore na panel
            PrikaziPrvoPitanje( _igra.Aktivno_pitanje );
        }

        /// <summary>
        /// Postavlja prvo pitanje i ponudene odgovore na odgovarajuci panel
        /// </summary>
        /// <param name="pitanje"></param>
        private void PrikaziPrvoPitanje( Pitanje pitanje )
        {
            lab_Pitanje.Text = pitanje.PrvoPitanje;
            txtOdgovorA.Text = pitanje.PrvoOdgovori[0];
            txtOdgovorB.Text = pitanje.PrvoOdgovori[1];
            txtOdgovorC.Text = pitanje.PrvoOdgovori[2];

            lab_Pitanje.Visible = true;
            txtOdgovorA.Visible = true;
            txtOdgovorB.Visible = true;
            txtOdgovorC.Visible = true;

            ShowPanel_prvo( );
            // postavi brojac kratkog timera na 5 i pokreni ga
            _igra.Brojac_kratki = 6;
            _igra.timer_pitanja.Enabled = true;
        }

        /// <summary>
        /// Postavlja drugo pitanje i ponudene odgovore na odgovarajuci panel
        /// </summary>
        /// <param name="pitanje"></param>
        private void PrikaziDrugoPitanje( Pitanje pitanje )
        {
            // ispisi pitanje i prikazi panel
            lab_Pitanje2.Text = pitanje.DrugoPitanje;
            ShowPanel_drugo( );
            // postavi brojac kratkog timera na 10 i pokreni ga
            _igra.Brojac_kratki = 21;
            _igra.timer_pitanja.Enabled = true;
        }

        /// <summary>
        /// Metoda poziva novu formu koja ispisuje najbolje rezultate.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void NajboljiRezultati_Click( object sender, EventArgs e )
        {
            LED.Vibrate( MILISEC_VibrateClick );
            var ih = new IspisHighscore(-1);
            ih.Enabled = true;
            ih.Show( );
        }

        /// <summary>
        /// Gumb pokrece formu o igri.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void menuItem5_Click( object sender, EventArgs e )
        {
            LED.Vibrate( MILISEC_VibrateClick );
            var o_igri = new OIgri {Enabled = true};
            o_igri.Show();
        }

        #region Ispis točno netočno
        /// <summary>
        /// Metoda ispisuje poruku o točnosti odgovora.
        /// </summary>
        public void PrikaziTocno()
        {
            Zvuk.Zvuk_Tocno();
            lab_tocno_netocno.Text = "TOČNO! :) !";
            lab_tocno_netocno.BackColor = Color.Green;
            inputPanel1.Enabled = false;
            Refresh();
        }
        /// <summary>
        /// Metoda ispisuje poruku o NEtočnosti odgovora.
        /// </summary>
        public void PrikaziKrivo()
        {
            Zvuk.Zvuk_Netocno();
            lab_tocno_netocno.Text = "Netočno! :(";
            lab_tocno_netocno.BackColor = Color.Red;
            inputPanel1.Enabled = false;
            Refresh( );
        }
        /// <summary>
        /// Postavljanje ispisa u početno stanje;
        /// </summary>
        private void ResetirajTocno()
        {
            lab_tocno_netocno.Text = string.Empty;
            lab_tocno_netocno.BackColor = Color.FromArgb(192, 192, 255);

            Refresh();
        }
        /// <summary>
        /// Metoda pauzira dretvu na zadani broj sekundi.
        /// </summary>
        /// <param name="sec"></param>
        public void Pricekaj(int sec)
        {
            Thread.Sleep( SEKUNDA * sec );
        }

        #endregion

        /// <summary>
        /// Obradjuje klik na ponudeni odgovor, te poziva drugo pitanje ako je tocan
        /// ili se vraca na glavni ekran ako je odgovor kriv
        /// </summary>
        /// <param name="odgovor">odgovor</param>
        private void ObradiOdgovorKlikom( string odgovor )
        {
            LED.Vibrate( MILISEC_VibrateClick );
            // zaustavi kratki timer
            _igra.timer_pitanja.Enabled = false;

            if ( _igra.ProvjeriOdgovor( odgovor, true ) )
            {
                // dodaj nove bodove
                _igra.Rezultat += _igra.Aktivno_pitanje.OdrediBrojBodova( true );

                PrikaziTocno();
                Pricekaj( 2 );
                ResetirajTocno( );

                // predji na drugo pitanje
                PrikaziDrugoPitanje( _igra.Aktivno_pitanje );
            }
            else
            {
                PrikaziKrivo( );
                // vrati se na glavni meni nakon sekunde
                Pricekaj( 2 );
                ResetirajTocno( );
                // resetiraj brojac tocnih zaredom
                tocnih_zaredom = 0;

                // vrati se na glavni izbornik s pitanjima
                ShowPanel_glavni( );
            }
        }

        /// <summary>
        /// Obradjuje se poslani odgovor na drugo pitanje ili jackpot.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_SaljiOdgovor_Click_1( object sender, EventArgs e )
        {
            LED.Vibrate( MILISEC_VibrateClick );
            // zaustavi kratki timer
            _igra.timer_pitanja.Enabled = false;

            if (_igra.ProvjeriOdgovor(txt_odgovor2.Text, false))
            {
                if (tocnih_zaredom != 3)
                {
                    // dodaj nove bodove
                    _igra.Rezultat += _igra.Aktivno_pitanje.OdrediBrojBodova(false);

                    // zakljucaj to pitanje
                    ZatvoriPitanje( ); 

                    // pocni brojanje tocnih za jackpot
                    tocnih_zaredom++;
                }
                else
                {
                    _igra.Rezultat += _igra.Aktivno_pitanje.OdrediBrojBodovaJackpot( _igra.Rezultat );
                    tocnih_zaredom = 0;
                }

                PrikaziTocno();
                Refresh();
                // pricekaj 2 sekunde
                Pricekaj(2);
                ResetirajTocno();

                // vrati se u glavni meni
                ShowPanel_glavni();
            }
            else
            {
                //resetiraj brojac tocnih zaredom
                tocnih_zaredom = 0;

                PrikaziKrivo( );
                // vrati se na glavni meni nakon sekunde
                Pricekaj( 2 );
                ResetirajTocno( );
                // vrati se na glavni izbornik s pitanjima
                ShowPanel_glavni( );
            }
        }

        /// <summary>
        /// Metoda zatvra pitanje i po potrebi uvodi JDS pitanja.
        /// </summary>
        private void ZatvoriPitanje()
        {
            // zakljucaj to pitanje
            AktivnaSlika.Enabled = false;
            AktivnaSlika.Image = OdrediSlikuRjeseno(_igra.Aktivno_pitanje.Kategorija);
            zatvorenih_slika_pitanje_ukupno++;
            zatvorenih_po_kategoriji[AktivnaSlika.Pitanje.Kategorija]++;

            // provjeri treba li ubaciti JDS pitanje (slucaj kada je jedna kategorija potrosena)
            if (zatvorenih_po_kategoriji[AktivnaSlika.Pitanje.Kategorija]==4 && !iskoristen_JDS )
            {
                // jds se moze samo jednom iskoristiti
                iskoristen_JDS = true;

                // odredi sve slika_pitanje te kategorije
                var slika_pitanja_kategorije = ( from n in lista_okvira
                                                 where n.Pitanje.Kategorija == AktivnaSlika.Pitanje.Kategorija
                                                 select n ).ToList( );
                // dohvati jds pitanja
                var pitanja_JDS = DohvatiIzBaze.DohvatiKategoriju( KategorijaPitanja.JDS );
                var rand = new Random( );
                // postavi pitanja
                for (int i=0; i<slika_pitanja_kategorije.Count();i++)
                {
                    slika_pitanja_kategorije[i].Pitanje = pitanja_JDS[rand.Next(0,pitanja_JDS.Count-1)];
                    slika_pitanja_kategorije[i].Image = OdrediSliku(KategorijaPitanja.JDS);
                    slika_pitanja_kategorije[i].Enabled = true;
                }
            }
        }

        /// <summary>
        /// Metoda prikazuje jackpot pitanje
        /// </summary>
        private void PrikaziJapot()
        {
            Zvuk.Zvuk_OtvoriJackpot();
            lab_tocno_netocno.Text = "JACKPOT!";
            var jackpot_pitanja = DohvatiIzBaze.DohvatiKategoriju(KategorijaPitanja.Jackpot);
            var random = new Random( );
            _igra.Aktivno_pitanje = jackpot_pitanja[random.Next(0, jackpot_pitanja.Count - 1)];

            PrikaziDrugoPitanje( _igra.Aktivno_pitanje );
        }

        #region Prikaz odgovarajuceg panela
        /// <summary>
        /// Metoda prikazuje glavni panel na kojem se nalaze pitanja
        /// </summary>
        private void ShowPanel_glavni( )
        {
            panelPitanje.Visible = false;
            panelPitanje2.Visible = false;
            PanelSlikePitanja4x4.Visible = true;
            lab_tocno_netocno.Text = "Reza:" + _igra.Rezultat;
            //lab_tocno_netocno.Text = string.Empty;
            lab_preostalo_sekundi.Text = string.Empty;

            if (tocnih_zaredom == 3)
            {
                PrikaziJapot();
            }
        }
        /// <summary>
        /// Metoda prikazuje prvo pitanje.
        /// </summary>
        private void ShowPanel_prvo( )
        {
            panelPitanje2.Visible = false;
            PanelSlikePitanja4x4.Visible = false;
            panelPitanje.Visible = true;

            //lab_tocno_netocno.Text = string.Empty;
            lab_preostalo_sekundi.Text = string.Empty;
        }
        /// <summary>
        /// Metoda prikazuje drugo pitanje.
        /// </summary>
        private void ShowPanel_drugo( )
        {
            // pocisti odgovor
            txt_odgovor2.Text = string.Empty;

            panelPitanje.Visible = false;
            PanelSlikePitanja4x4.Visible = false;
            panelPitanje2.Visible = true;
            lab_Pitanje2.Visible = true;
            txt_odgovor2.Visible = true;
            // prikazi tipkovnicu
            inputPanel1.Enabled = true;

            Refresh( );
            //lab_tocno_netocno.Text = string.Empty;
            lab_preostalo_sekundi.Text = string.Empty;
        }
        #endregion

        #region Hvatanje klikova na ponudjene odgovore

        private void prvoOdg1_Click( object sender, EventArgs e )
        {
            ObradiOdgovorKlikom( txtOdgovorA.Text );
        }

        private void prvoOdg2_Click( object sender, EventArgs e )
        {
            ObradiOdgovorKlikom( txtOdgovorB.Text );
        }

        private void prvoOdg3_Click( object sender, EventArgs e )
        {
            ObradiOdgovorKlikom( txtOdgovorC.Text );
        }

        #endregion

        #region Hvatanje klikova na pitanja

        private void slikaPitanje_11_Click( object sender, EventArgs e )
        {
            ObradiKlikPitanja( sender );
        }

        private void slikaPitanje_12_Click( object sender, EventArgs e )
        {
            ObradiKlikPitanja( sender );
        }

        private void slikaPitanje_13_Click( object sender, EventArgs e )
        {
            ObradiKlikPitanja( sender );
        }

        private void slikaPitanje_14_Click( object sender, EventArgs e )
        {
            ObradiKlikPitanja( sender );
        }

        private void slikaPitanje_21_Click( object sender, EventArgs e )
        {
            ObradiKlikPitanja( sender );
        }

        private void slikaPitanje_22_Click( object sender, EventArgs e )
        {
            ObradiKlikPitanja( sender );
        }

        private void slikaPitanje_23_Click( object sender, EventArgs e )
        {
            ObradiKlikPitanja( sender );
        }

        private void slikaPitanje_24_Click( object sender, EventArgs e )
        {
            ObradiKlikPitanja( sender );
        }

        private void slikaPitanje_31_Click( object sender, EventArgs e )
        {
            ObradiKlikPitanja( sender );
        }

        private void slikaPitanje_32_Click( object sender, EventArgs e )
        {
            ObradiKlikPitanja( sender );
        }

        private void slikaPitanje_33_Click( object sender, EventArgs e )
        {
            ObradiKlikPitanja( sender );
        }

        private void slikaPitanje_34_Click( object sender, EventArgs e )
        {
            ObradiKlikPitanja( sender );
        }

        private void slikaPitanje_41_Click( object sender, EventArgs e )
        {
            ObradiKlikPitanja( sender );
        }

        private void slikaPitanje_42_Click( object sender, EventArgs e )
        {
            ObradiKlikPitanja( sender );
        }

        private void slikaPitanje_43_Click( object sender, EventArgs e )
        {
            ObradiKlikPitanja( sender );
        }

        private void slikaPitanje_44_Click( object sender, EventArgs e )
        {
            ObradiKlikPitanja( sender );
        }

        #endregion

        /// <summary>
        /// Zatvaranje playera.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void GlavnaForma_Closed(object sender, EventArgs e)
        {
            Zvuk.Zatvori( );
        }

        /// <summary>
        /// Zaustavljanje i predaja trenutne igre.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void predajIgru_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("Predajete igru. Nastavi?", "Predaja igre.", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1)==DialogResult.Yes)
            {
                _igra.Ukupni_broj_sekundi = 1;
            }
        }

        /// <summary>
        /// Pokrece novu igru (preko slike)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void pic_glavni_nova_igra_Click(object sender, EventArgs e)
        {
            NovaIgra_Click( sender, e );
            panel_glavni_izbornik.Visible = false;
        }


        /// <summary>
        /// Izlaz iz igre.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void menuItem1_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("Izlazite iz igre. Nastavi?", "Izlaz.", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == DialogResult.Yes)
            {
                Application.Exit( );
            }
        }

        /// <summary>
        /// Prikaz najboljiz rezultata.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void pic_glavni_najboljirezultati_Click(object sender, EventArgs e)
        {
            NajboljiRezultati_Click( sender, e );
        }
    }
}